package com.xiaoyu.lanling;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.os.Process;
import android.util.Log;

import androidx.multidex.MultiDex;
import androidx.multidex.MultiDexApplication;

import com.xiaoyu.ambulance.resegence.Resurgence;
import com.xiaoyu.base.AppConfig;
import com.xiaoyu.base.app.App;
import com.xiaoyu.base.app.AppEngine;
import com.xiaoyu.base.app.Trimmable;
import com.xiaoyu.base.data.CacheData;
import com.xiaoyu.base.push.BasePushAgent;
import com.xiaoyu.lanling.app.InitProcessor;
import com.xiaoyu.lanling.app.MultiProcessInitProcessor;
import com.xiaoyu.lanling.base.push.PushAgent;
import com.xiaoyu.lanling.data.AppStateData;
import com.xiaoyu.lanling.data.ConfigData;
import com.xiaoyu.lanling.feature.newtips.data.NewTipData;
import com.xiaoyu.lanling.feature.push.PushData;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import in.srain.cube.Cube;
import in.srain.cube.app.init.InitializableAsync;
import in.srain.cube.app.init.InitializableOneWay;
import in.srain.cube.app.init.InitializableSync;
import in.srain.cube.util.CLog;
import in.srain.cube.util.Env;
import in.srain.cube.util.UTUtil;
import in.srain.cube.util.log.LogProxy;
import in.srain.cube.util.time.TimeData;
import io.reactivex.plugins.RxJavaPlugins;

public class BaseApplication extends MultiDexApplication implements Resurgence.FatalOccurListener {

    public static final boolean DEBUG = BuildConfig.DEBUG;

    private final String TAG = "BaseApplication";

    private List<Trimmable> mTrimmableList = new LinkedList<>();

    @Override
    public void onCreate() {
        super.onCreate();
        showStatus("onCreate");

        RxJavaPlugins.setErrorHandler(throwable -> {
        });

        Env.setEnvTag(AppConfig.envKey());
        UTUtil.getInstance().setContext(this);

        CLog.setLogLevel(BuildConfig.DEBUG ? CLog.LEVEL_VERBOSE : CLog.LEVEL_INFO);
        CLog.setHandler(LogProxy.getInstance());

        Cube.onCreate(this);

        App.getInstance().onCreate(this);

//        if(Env.isDevOrInDevMode()){
//            Stetho.initializeWithDefaults(this);
//        }

        MultiProcessInitProcessor.Companion.init(this);

        if (!Cube.getInstance().isMainProcess()) {
            CLog.i(TAG, "is not main process, finish initialization: %s", Cube.getInstance().getProcessName());
            return;
        }

        TimeData.getInstance().initStartTime();

        final Application app = this;

        final List<Object> initList = new ArrayList<>();

        initList.add(CacheData.getInstance());
        initList.add(new InitProcessor(app));
        initList.add(ConfigData.getInstance());
        initList.add(AppStateData.Companion.getInstance());
        initList.add(NewTipData.Companion.getInstance());

        BasePushAgent pushAgent = PushAgent.getInstance();
        pushAgent.setPushEventListener(PushData.getInstance());
        initList.add(pushAgent);

        final AppEngine appEngine = AppEngine.getInstance();
        for (Object item : initList) {
            if (item instanceof InitializableSync) {
                appEngine.addSyncInitComponents((InitializableSync) item);
            }
            if (item instanceof InitializableAsync) {
                appEngine.addAsyncInitComponents((InitializableAsync) item);
            }
            if (item instanceof InitializableOneWay) {
                appEngine.addOneWayInitComponents((InitializableOneWay) item);
            }
            if (item instanceof Trimmable) {
                mTrimmableList.add((Trimmable) item);
            }
        }
        appEngine.start(app);
        Resurgence.Companion.start();
        Resurgence.Companion.registerFatalListener(this);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        showStatus("onLowMemory");
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        showStatus("onTerminate");
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        showStatus("onTrimMemory");

        for (Trimmable trimmable : mTrimmableList) {
            trimmable.onTrimMemory(level);
        }
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
        showStatus("attachBaseContext");
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        showStatus("onConfigurationChanged");
    }

    protected void showStatus(String status) {
        if (!DEBUG) {
            return;
        }
        final String[] className = ((Object) this).getClass().getName().split("\\.");
        Log.d("cp-lifecycle", String.format("%s %s %s", className[className.length - 1], status, this));
    }

    @Override
    public void onFatalOccur() {
        Activity topActivity = App.getInstance().getTopActivity();
        if (topActivity != null && (topActivity.isFinishing() || topActivity.isDestroyed())) {
            Process.killProcess(Process.myPid());
            return;
        }
        new AlertDialog.Builder(topActivity)
                .setMessage(R.string.exit_on_fatal)
                .setCancelable(false)
                .setPositiveButton("退出", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Process.killProcess(Process.myPid());
                    }
                })
                .create().show();
    }
}